import logging
from typing import Annotated
from fastapi import Depends
from aioredis import Redis, RedisError
from app.config import get_settings

uvicorn_logger = logging.getLogger('uvicorn')


class RedisPool:
    _redis_pool = {}

    @classmethod
    async def create_pool(cls):
        settings = get_settings()
        url = settings.REDIS_URL
        await cls._connect_db(url, settings.AUTH_SESSION_REDIS_DB)
        await cls._connect_db(url, settings.CARD_TOKEN_REDIS_DB)
        await cls._connect_db(url, settings.API_NONCE_REDIS_DB)
        await cls._connect_db(url, settings.BACKEND_NONCE_REDIS_DB)
        await cls._connect_db(url, settings.BACKEND_DFP_REDIS_DB)
        await cls._connect_db(url, settings.BACKEND_IP_REDIS_DB)

    @classmethod
    async def _connect_db(cls, url: str, index: int):
        try:
            redis = await Redis.from_url(url + f'/{index}', decode_responses=True)
            await redis.info()
            cls._redis_pool.update({index: redis})
            uvicorn_logger.info(f"Redis DB {index} connection created.")
        except RedisError as e:
            uvicorn_logger.error(f"Failed to create Redis DB {index} connection: {e}")
            return

    @classmethod
    def get_redis(cls, db: int) -> Redis:
        redis = cls._redis_pool.get(db)
        if not redis:
            raise RuntimeError(f"Redis DB {db} not found")
        return redis

    @classmethod
    async def close_pool(cls):
        for db, redis in cls._redis_pool.items():
            try:
                await redis.close()
                uvicorn_logger.info(f"Redis DB {db} connection closed.")
            except RedisError as e:
                uvicorn_logger.error(f"Failed to close Redis DB {db}: {e}")


async def create_redis_pool():
    """创建 Redis 连接池"""
    await RedisPool.create_pool()


async def init_db():
    """初始化 Redis 数据库"""
    await create_redis_pool()


async def close_db():
    """关闭 Redis 连接池"""
    await RedisPool.close_pool()


def get_auth_session_redis():
    return RedisPool.get_redis(get_settings().AUTH_SESSION_REDIS_DB)


def get_card_token_redis():
    return RedisPool.get_redis(get_settings().CARD_TOKEN_REDIS_DB)


def get_api_nonce_redis():
    return RedisPool.get_redis(get_settings().API_NONCE_REDIS_DB)


def get_backend_nonce_redis():
    return RedisPool.get_redis(get_settings().BACKEND_NONCE_REDIS_DB)


def get_backend_dfp_redis():
    return RedisPool.get_redis(get_settings().BACKEND_DFP_REDIS_DB)

def get_backend_ip_redis():
    return RedisPool.get_redis(get_settings().BACKEND_IP_REDIS_DB)


AuthSessionRedisDep = Annotated[Redis, Depends(get_auth_session_redis)]
CardTokenRedisDep = Annotated[Redis, Depends(get_card_token_redis)]
APINonceRedisDep = Annotated[Redis, Depends(get_api_nonce_redis)]
BackendNonceRedisDep = Annotated[Redis, Depends(get_backend_nonce_redis)]
BackendDFPRedisDep = Annotated[Redis, Depends(get_backend_dfp_redis)]
BackendIPRedisDep = Annotated[Redis, Depends(get_backend_ip_redis)]
RedisError = RedisError
